package fanxing;

import fanxing.IDataSet;
import fanxing.VisitInfo;

import java.util.ArrayList;
import java.util.List;

public class Main {

    public void main() {
        // 1.从服务器拿到的是VisitInfo的list
        List<VisitInfo> list = new ArrayList<>();
        setData(list);
    }

    /**
     * 封装中使用IDataSet接口
     *
     * @param list 只能读取，不能add
     */
    public void setData(List<? extends IDataSet> list) {
        // 取出list中的dataSet,然后就可以做操作
        IDataSet dataSet = list.get(0);
        float percent = dataSet.getPercent();
        String value = dataSet.getValue();
    }



    public void fun() {
        List<IDataSet> list1 = new ArrayList<>();
        List<VisitInfo> list2 = new ArrayList<>();
        List<? extends IDataSet> list3 = new ArrayList<>();

        init1(list1);
//        init1(list2); // Error 不认为List<VisitInfo>与List<IDataSet>类型匹配

        init2(list1);
        init2(list2);
        init2(list3);

        init3(list1);
//        init3(list2); // Error

        IDataSet dataSet = new VisitInfo();
        init4(list1);
        init4(list2);
        init4(list3);

        init4(list1, dataSet);
        init4(list2, new VisitInfo());
    }

    private void init1(List<IDataSet> list) {
        // 可以向list中add IDataSet类型的数据
        list.add(new VisitInfo());
        IDataSet dataSet = list.get(0);
    }

    // 通配符：通配任何IDataSet的子类，但是由于未指定，所以不能向List中添加任何对象，包括IDataSet（可以add(null）
    private void init2(List<? extends IDataSet> list) {
        IDataSet dataSet = list.get(0);
        // fixme 不可以向list中添加 IDataSet
//        list.add(new VisitInfo()); // error
    }

    // super:声明通配符是由某个特定类的任何基类来界定，通配任意IDataSet的父类，可以add IDataSet的任何子类
    private void init3(List<? super IDataSet> list) {
        Object o = list.get(0);
//        list.add(new VisitInfo()); // 为什么可以add
    }

    public <T extends IDataSet> void init4(List<T> list) {
        // 泛型擦除 T 被变为IDataSet,所以如果list<IDataSet>.add(T)是可以的，那么认为是匹配的
        IDataSet dataSet = new VisitInfo();
//        list.add(dataSet); // error
    }


    // 泛型只有extends,泛型擦除时只能向上转型，
    public <T extends IDataSet> void init4(List<T> list, T t) {
        // 泛型擦除 T 被变为IDataSet,所以如果list<IDataSet>.add(T)是可以的，那么认为是匹配的
        IDataSet dataSet = new VisitInfo();
//        list.add(dataSet); // error
        list.add(t);
    }


    /**
     * 泛型 修饰方法，放在返回值的前面
     *
     * @param t
     * @param <T> 任意类型
     * @return
     */
    public <T> T nor(T t) {
        return t;
    }

    /**
     * 限定必须是IDataSet的子类
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends IDataSet> T nor(T t) {
        return t;
    }

    public <T> T nor(List<? extends T> list) {
        T t = list.get(0);
        return t;
    }
}
